import java.io.*;
import java.util.Scanner;

// 基本的IO流接口，继承 AutoCloseable 以支持 try-with-resources
interface Stream extends AutoCloseable {
    int read() throws IOException;
    void write(int b) throws IOException;
    void close() throws IOException; // 显式声明 close 方法
}

// 基本文件流实现
class FileStream implements Stream {
    private FileInputStream inputStream;
    private FileOutputStream outputStream;

    public FileStream(String filePath, boolean isInput) throws IOException {
        if (isInput) {
            this.inputStream = new FileInputStream(filePath);
        } else {
            this.outputStream = new FileOutputStream(filePath);
        }
    }

    @Override
    public int read() throws IOException {
        if (inputStream != null) {
            return inputStream.read();
        }
        throw new IOException("输入流未初始化");
    }

    @Override
    public void write(int b) throws IOException {
        if (outputStream != null) {
            outputStream.write(b);
        } else {
            throw new IOException("输出流未初始化");
        }
    }

    @Override
    public void close() throws IOException {
        if (inputStream != null) inputStream.close();
        if (outputStream != null) outputStream.close();
    }
}

// 抽象装饰器类
abstract class StreamDecorator implements Stream {
    protected Stream decoratedStream;

    public StreamDecorator(Stream decoratedStream) {
        this.decoratedStream = decoratedStream;
    }

    @Override
    public int read() throws IOException {
        return decoratedStream.read();
    }

    @Override
    public void write(int b) throws IOException {
        decoratedStream.write(b);
    }

    @Override
    public void close() throws IOException {
        decoratedStream.close();
    }
}

// 加密/解密装饰器（使用简单的XOR加密）
class CryptoStreamDecorator extends StreamDecorator {
    private final int key; // 加密密钥（简单示例使用单一字节）

    public CryptoStreamDecorator(Stream decoratedStream, int key) {
        super(decoratedStream);
        this.key = key;
    }

    @Override
    public int read() throws IOException {
        int data = super.read();
        if (data != -1) {
            return data ^ key; // XOR解密
        }
        return data;
    }

    @Override
    public void write(int b) throws IOException {
        super.write(b ^ key); // XOR加密
    }
}

public class FileEncryptionDemo {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入源文件路径: ");
        String sourcePath = scanner.nextLine();
        System.out.print("请输入加密后文件路径: ");
        String encryptedPath = scanner.nextLine();
        System.out.print("请输入解密后文件路径: ");
        String decryptedPath = scanner.nextLine();
        int cryptoKey = 0x5A; // 示例密钥（可替换为更复杂的加密算法）

        // 检查源文件是否存在
        File sourceFile = new File(sourcePath);
        if (!sourceFile.exists()) {
            System.out.println("源文件不存在！");
            scanner.close();
            return;
        }

        // 写入加密文件
        try (Stream fileStream = new FileStream(sourcePath, true);
             Stream cryptoStream = new CryptoStreamDecorator(new FileStream(encryptedPath, false), cryptoKey)) {
            System.out.println("正在加密并写入文件: " + encryptedPath);
            int data;
            while ((data = fileStream.read()) != -1) {
                cryptoStream.write(data);
            }
        } catch (IOException e) {
            System.err.println("加密写入错误: " + e.getMessage());
        }

        // 读取加密文件并解密
        try (Stream cryptoStream = new CryptoStreamDecorator(new FileStream(encryptedPath, true), cryptoKey);
             Stream fileStream = new FileStream(decryptedPath, false)) {
            System.out.println("正在解密并写入文件: " + decryptedPath);
            int data;
            while ((data = cryptoStream.read()) != -1) {
                fileStream.write(data);
            }
        } catch (IOException e) {
            System.err.println("解密写入错误: " + e.getMessage());
        }

        // 读取解密文件内容并显示
        try (BufferedReader reader = new BufferedReader(new FileReader(decryptedPath))) {
            System.out.println("\n解密文件内容:");
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.err.println("读取解密文件错误: " + e.getMessage());
        }

        scanner.close();

        // 讨论与问答
        // 1. 装饰器模式如何简化IO流的扩展
        //   动态扩展：通过装饰器动态添加功能（如加密），无需修改原始流类。
        //   模块化：每个装饰器专注于单一功能（如加密、压缩），易于组合。
        //   复用性：装饰器可应用于任何实现Stream接口的类，灵活性高。
        //   代码清晰：将扩展功能与核心逻辑分离，符合单一职责原则。

        // 2. 装饰器模式相比直接继承InputStream的优势
        //   灵活性：装饰器支持运行时组合多个功能，而继承是静态的。
        //   避免类爆炸：继承需要为每种组合创建子类，装饰器通过组合避免此问题。
        //   可重用：装饰器可复用于不同流类型（如文件流、网络流）。
        //   开闭原则：装饰器模式对扩展开放、对修改关闭，易于维护。

        // 3. 如何创建其他自定义IO流装饰器
        //   定义新装饰器：继承StreamDecorator，添加新功能（如压缩、日志记录）。
        //   组合装饰器：按需组合多个装饰器（如CryptoStreamDecorator后接CompressionStreamDecorator）。
        //   参数化配置：通过构造参数支持不同配置（如加密算法、密钥）。
        //   扩展接口：为特定场景（如网络流）定义新接口方法，适配更多流类型。
    }
}